#include "StringTests.h"
#include "../TestFramework/TestString.h"

namespace
{
    bool IsEqualStrings(const char* lhs, const char* rhs)
    {
        while (*lhs++ == *rhs++)
        {
            if (*lhs == '\0' && *rhs == '\0')
            {
                return true;
            }

            if (*lhs == '\0' || *rhs == '\0')
            {
                break;
            }
        }

        return false;
    }

    TEST_CASE(TestStringCreation)
    {
        TestFramework::TestString string("spartak");
        const char* str = "spartak";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str1, str));
    }
    
    TEST_CASE(TestStringCreation1)
    {
        TestFramework::TestString string('c', 4);
        const char* str = "cccc";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str1, str));
    }
    
    TEST_CASE(TestStringCreation2)
    {
        TestFramework::TestString string("123456", 1, 3);
        const char* str = "234";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str1, str));
    }

    TEST_CASE(TestStringSum)
    {
        TestFramework::TestString string("123456");
        TestFramework::TestString string1("123456");
        TestFramework::TestString string2 = string + string1;
        const char* str = "123456123456";
        const char* str1 = string2.Data();
        CHECK(IsEqualStrings(str1, str));
    }

    TEST_CASE(TestStringSum1)
    {
        TestFramework::TestString string("123456");
        TestFramework::TestString string1("123456");
        string1 += string;
        const char* str = "123456123456";
        const char* str1 = string1.Data();
        CHECK(IsEqualStrings(str1, str));
    }

    TEST_CASE(TestStringAppend)
    {
        char* string1 = "123456";
        TestFramework::TestString string("123456");
        string.Append(string1);
        const char* str = "123456123456";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str1, str));
    }
    
    TEST_CASE(TestStringInsert1)
    {
        TestFramework::TestString string("123456");
        const char* string1 = "123";
        string.Insert(2, string1);
        const char* str = "121233456";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str1, str));
    }

    TEST_CASE(TestStringInsert2)
    {
        TestFramework::TestString string("123456");
        TestFramework::TestString string1("123");
        string.Insert(2, string1);
        const char* str = "121233456";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str1, str));
    }

    TEST_CASE(TestStringClear)
    {
        TestFramework::TestString string("123456");
        string.Clear();
        const char* str = "";
        const char* str1 = string.Data();
        CHECK(*str1 == *str);
    }

    TEST_CASE(TestStringErase)
    {
        TestFramework::TestString string("123456");
        string.Erase(1, 2);
        const char* str = "1456";
        const char* str1 = string.Data();
        CHECK(*str1 == *str);
    }

    TEST_CASE(TestStringErase1)
    {
        TestFramework::TestString string("123456");
        string.Erase(5, 2);
        const char* str = "12345";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str1, str));
    }

    TEST_CASE(TestStringErase2)
    {
        TestFramework::TestString string("123456");
        string.Erase(10, 20);
        const char* str = "123456";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str1, str));
    }

    TEST_CASE(TestStringData)
    {
        TestFramework::TestString string("123456");
        const char* data = string.Data();
        CHECK(std::strlen(data) == 6);
    }

    TEST_CASE(TestStringSwap)
    {
        std::string st1("12");
        std::string st2("21");
        st1.swap(st2);
        TestFramework::TestString string("123456");
        TestFramework::TestString string1("654321");
        string.Swap(string1);
        const char* str = "654321";
        const char* str1 = string.Data();
        const char* str0 = "123456";
        const char* str2 = string1.Data();
        CHECK(IsEqualStrings(str1, str) && IsEqualStrings(str2, str0));
    }

    TEST_CASE(TestStringReplace1)
    {
        TestFramework::TestString string("123456");
        const char* str = "abc";
        string.Replace(2, 3, str);
        const char* str0 = "12abc6";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str0, str1));
    }

    TEST_CASE(TestStringReplace2)
    {
        TestFramework::TestString string("123456");
        const char* str = "abc";
        string.Replace(5, 3, str);
        const char* str0 = "12345a";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str0, str1));
    }

    TEST_CASE(TestStringReplace3)
    {
        TestFramework::TestString string("123456");
        const char* str = "abc";
        CHECK_EXCEPTION_OCCURRENCE(string.Replace(10, 10, str));
    }

    TEST_CASE(TestStringReplace4)
    {
        TestFramework::TestString string("123456");
        TestFramework::TestString str("abc");
        string.Replace(1, 3, str);
        const char* str0 = "1abc56";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str0, str1));
    }

    TEST_CASE(TestStringReplace5)
    {
        TestFramework::TestString string("123456");
        TestFramework::TestString str("abc");
        string.Replace(5, 3, str);
        const char* str0 = "12345a";
        const char* str1 = string.Data();
        CHECK(IsEqualStrings(str0, str1));
    }

    TEST_CASE(TestStringReplace6)
    {
        TestFramework::TestString string("123456");
        TestFramework::TestString str("abc");
        CHECK_EXCEPTION_OCCURRENCE(string.Replace(10, 10, str));
    }

    TEST_CASE(TestStringCompare1)
    {
        TestFramework::TestString string("123456");
        TestFramework::TestString string1("23456");
        CHECK(string.Compare(string1) == 1);
    }

    TEST_CASE(TestStringCompare2)
    {
        TestFramework::TestWString string(L"23456");
        TestFramework::TestWString string1(L"123456");
        CHECK(string.Compare(string1) == -1);
    }

    TEST_CASE(TestStringCompare3)
    {
        TestFramework::TestString string("123456");
        TestFramework::TestString string1("123456");
        CHECK(string.Compare(string1) == 0);
    }

    TEST_CASE(TestStringCompare4)
    {
        TestFramework::TestString string("123456");
        const char* string1 = "23456";
        CHECK(string.Compare(string1) == 1);
    }

    TEST_CASE(TestStringCompare5)
    {
        TestFramework::TestString string("23456");
        const char* string1 = "123456";
        CHECK(string.Compare(string1) == -1);
    }

    TEST_CASE(TestStringCompare6)
    {
        TestFramework::TestString string("123456");
        const char* string1 = "123456";
        CHECK(string.Compare(string1) == 0);
    }

    TEST_CASE(TestStringSqaureBrackets)
    {
        TestFramework::TestString string("123456");
        CHECK(string[1] == '2');
    }

    TEST_CASE(TestStringFindSubstring)
    {
        TestFramework::TestString baseStr("Hello, World");
        CHECK(baseStr.Find(TestFramework::TestString("Mama mila ramu!")) == TestFramework::TestString::NPos);
        CHECK(baseStr.Find(TestFramework::TestString("Hello")) != TestFramework::TestString::NPos);
        CHECK(baseStr.Find(TestFramework::TestString("World")) != TestFramework::TestString::NPos);
        CHECK(baseStr.Find(TestFramework::TestString(",")) != TestFramework::TestString::NPos);
        CHECK(baseStr.Find(TestFramework::TestString("test")) == TestFramework::TestString::NPos);
        CHECK(baseStr.Find(TestFramework::TestString("WorldWideWeb")) == TestFramework::TestString::NPos);
    }

    START_TEST_SUITE(StringTest, "String test")
    {
        REGISTER_TEST(TestStringCreation);
        REGISTER_TEST(TestStringCreation1);
        REGISTER_TEST(TestStringCreation2);
        REGISTER_TEST(TestStringSum);
        REGISTER_TEST(TestStringSum1);
        REGISTER_TEST(TestStringAppend);
        REGISTER_TEST(TestStringInsert1);
        REGISTER_TEST(TestStringInsert2);
        REGISTER_TEST(TestStringClear);
        REGISTER_TEST(TestStringErase);
        REGISTER_TEST(TestStringErase1);
        REGISTER_TEST(TestStringErase2);
        REGISTER_TEST(TestStringData);
        REGISTER_TEST(TestStringSwap);
        REGISTER_TEST(TestStringReplace1);
        REGISTER_TEST(TestStringReplace2);
        REGISTER_TEST(TestStringReplace3);
        REGISTER_TEST(TestStringReplace4);
        REGISTER_TEST(TestStringReplace5);
        REGISTER_TEST(TestStringReplace6);
        REGISTER_TEST(TestStringCompare1);
        REGISTER_TEST(TestStringCompare2);
        REGISTER_TEST(TestStringCompare3);
        REGISTER_TEST(TestStringCompare4);
        REGISTER_TEST(TestStringCompare5);
        REGISTER_TEST(TestStringCompare6);
        REGISTER_TEST(TestStringSqaureBrackets);
        REGISTER_TEST(TestStringFindSubstring);
    }
    FINISH_TEST_SUITE
}

namespace Tests
{
    TestFramework::UnitTestPtr CreateStringTester()
    {
        CREATE_SUITE(StringTest);
    }
}
